package abacab.remote.netty;

import java.io.ByteArrayOutputStream;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandler.Sharable;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import abacab.remote.ConnectionRegistry;
import abacab.remote.message.Message;
import abacab.remote.protocol.MessageProtocol;

/**
 * The encoder for sent messages
 */
@Sharable
public class MessageEncoder extends OneToOneEncoder {
	/** The logger */
	private static final Logger				logger	= LoggerFactory.getLogger(MessageEncoder.class);

	/** The connection registry */
	private final ConnectionRegistry	registry;

	/**
	 * Create the encoder
	 * 
	 * @param registry
	 *          the connection registry
	 */
	public MessageEncoder(ConnectionRegistry registry) {
		this.registry = registry;
	}

	@Override
	protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
		Message message;
		try {
			message = (Message) msg;
		}
		catch (ClassCastException e) {
			logger.warn("Unknown type of message: " + msg.getClass().getName(), e);
			return msg;
		}
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		MessageProtocol.encode(message, baos, this.registry.getSerilizationExt());
		ChannelBuffer buffer = ChannelBuffers.buffer(baos.size() + 2);
		buffer.writeShort(baos.size());
		buffer.writeBytes(baos.toByteArray());
		return buffer;
	}
}